import React, { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd';

import './index.less';

interface DraggableBodyRowProps
  extends React.HTMLAttributes<HTMLTableRowElement> {
  onDroping?: (key: string) => void;
  index: number;
  'data-row-key': string;
  moveRow: (
    dragIndex: number,
    hoverIndex: number,
    dragKey: string,
    hoverKey: string,
  ) => void;
}

const type = 'DraggableBodyRow';

const DraggableBodyRow = ({
  index,
  moveRow,
  className,
  style,
  onDroping,
  ...restProps
}: DraggableBodyRowProps) => {
  const ref = useRef<HTMLTableRowElement>(null);
  const hoverKey = restProps['data-row-key'];
  const [{ isOver,  dropClassName }, drop] = useDrop({
    accept: type,
    collect: (monitor) => {
      const { index: dragIndex, 'data-row-key': dragKey } =
        monitor.getItem() ?? {};

      if (dragKey === hoverKey) {
        return {};
      }

      if (monitor.canDrop()) {
        onDroping?.(dragKey);
      }
      return {
        isOver: monitor.isOver(),
        dropClassName:
          dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
      };
    },
    drop: (item: { index: number; 'data-row-key': string }) => {
      moveRow(item.index, index, item['data-row-key'], hoverKey);
    },
  });
  const [, drag] = useDrag({
    type,
    item: { index, 'data-row-key': hoverKey },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });
  drop(drag(ref));

  return (
    <tr
      ref={ref}
      className={`${className}${isOver ? dropClassName : ''}`}
      style={{ cursor: 'move', ...style }}
      {...restProps}
    />
  );
};

export default DraggableBodyRow;
